package com.elab.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

@Configuration
//@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

	/*@Autowired
	private BootSecurityProperties properties;*/
	@Autowired
    private AuthenticationProvider securityProvider;

	// 设置获取token的url
	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.csrf().disable();
		http.requestMatchers().antMatchers("/oauth/**","/login/**","/logout/**", "/login")
		.and()
		.authorizeRequests()
		.antMatchers("/oauth/**","/login/**","/logout/**", "/login").authenticated()
		.and()
		.formLogin()
		.loginPage("/login")    //跳转登录页面的控制器，该地址要保证和表单提交的地址一致！
		// 登录处理url
//        .loginProcessingUrl(properties.getLoginProcessUrl())
		.successHandler(new AuthenticationSuccessHandler() {
			@Override
			public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2)
					throws IOException, ServletException {
				Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
				if (principal != null && principal instanceof UserDetails) {
					UserDetails user = (UserDetails) principal;
					System.out.println("loginUser:"+user.getUsername());
					//维护在session中
					arg0.getSession().setAttribute("userDetail", user);
					arg1.sendRedirect("/");
				} 
			}
		})
		//失败处理
		.failureHandler(new AuthenticationFailureHandler() {
			@Override
			public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, 
					AuthenticationException authenticationException)
					throws IOException, ServletException {
				System.out.println("error"+authenticationException.getMessage());
				response.sendRedirect("/login");
			}
		})
		.permitAll()
		.and()
		.logout().logoutSuccessUrl("/")
		.permitAll();
	}

	//配置内存模式的用户
	@Bean
	@Override
	protected UserDetailsService userDetailsService(){
		InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
		manager.createUser(User.withUsername("demoUser1").password("123456").authorities("USER").build());
		manager.createUser(User.withUsername("demoUser2").password("123456").authorities("USER").build());
		manager.createUser(User.withUsername("demo").password("123456").authorities("USER").build());
		manager.createUser(User.withUsername("13192294560").password("248264emoker").authorities("USER").build());
		return manager;
	}

	/**
	 * 需要配置这个支持password模式
	 */
	@Override
	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	/******************************************
	 * 以下为实验性代码 1.0.0
	 ******************************************/
	// password 方案一：明文存储，用于测试，不能用于生产
	@Bean
	PasswordEncoder passwordEncoder(){
		return NoOpPasswordEncoder.getInstance();
	}
	/*@Bean
    public PasswordEncoder passwordEncoder () {
    	return new StandardPasswordEncoder();
    }*/

	/**
	 * 让Security 忽略这些url，不做拦截处理
	 *
	 * @param
	 * @throws Exception
	 */
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers
		("/swagger-ui.html/**", "/webjars/**",
				"/swagger-resources/**", "/v2/api-docs/**",
				"/swagger-resources/configuration/ui/**", "/swagger-resources/configuration/security/**",
				"/images/**", "/login");
	}
	@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //自定义AuthenticationProvider  
        auth.authenticationProvider(securityProvider);
    }
	/******************************************
	 * 以上为实验性代码 1.0.0
	 ******************************************/
}
